Namespace("sketch.framework.commands");

(function(cmd) {
    cmd.Align = klass(cmd.Command, {
        _constructor: function(name, description, elements){
            this.name(name);
            this.description(description);
            this._elements = elements;
        },

        execute: function(){
            if (this._elements.length === 0){
                return;
            }

            var center, space, leftmost, rightmost, topMost, bottomMost, sum, last;
            var baseElement = this._elements[0];
            var original = this._originalPositions = [];
            each(this._elements, function(element){
                original.push({element: element, position: element.position()});
            });

            switch (this.name()){
                case "left":
                    each(this._elements, function(element){ element.left(baseElement.left()); });
                    break;
                case "top":
                    each(this._elements, function(element){ element.top(baseElement.top()); });
                    break;
                case "right":
                    each(this._elements, function(element){ element.left(baseElement.right() - element.width()); });
                    break;
                case "bottom":
                    each(this._elements, function(element){ element.top(baseElement.bottom() - element.height()); });
                    break;
                case "center":
                    center = baseElement.left() + baseElement.width() / 2;
                    each(this._elements, function(element){ element.left(center - element.width() / 2); });
                    break;
                case "middle":
                    center = baseElement.top() + baseElement.height() / 2;
                    each(this._elements, function(element){ element.top(center - element.height() / 2); });
                    break;
                case "distributeHorizontally":
                    leftmost = sketch.util.elementWithMin(this._elements, function(e){ return e.left(); });
                    rightmost = sketch.util.elementWithMax(this._elements, function(e){ return e.right(); });
                    this._elements.sort(function(a,b){
                        var diff = a.left() - b.left();
                        if (diff !== 0){
                            return diff;
                        }

                        return a.width() - b.width();
                    });
                    sum = sketch.util.sum(this._elements, function(e){ return e.width(); });
                    space = ~~((rightmost.right() - leftmost.left() - sum) / (this._elements.length - 1));

                    last = leftmost;
                    each(this._elements, function(element){
                        if (element !== leftmost && element !== rightmost) {
                            element.left(last.right() + space);
                            last = element;
                        }
                    });
                    break;
                case "distributeVertically":
                    topMost = sketch.util.elementWithMin(this._elements, function(e){ return e.top(); });
                    bottomMost = sketch.util.elementWithMax(this._elements, function(e){ return e.bottom(); });
                    this._elements.sort(function(a,b){
                        var diff = a.top() - b.top();
                        if (diff !== 0){
                            return diff;
                        }

                        return a.height() - b.height();
                    });
                    sum = sketch.util.sum(this._elements, function(e){ return e.height(); });
                    space = ~~((bottomMost.bottom() - topMost.top() - sum) / (this._elements.length - 1));

                    last = topMost;
                    each(this._elements, function(element){
                        if (element !== topMost && element !== bottomMost) {
                            element.top(last.bottom() + space);
                            last = element;
                        }
                    });
                    break;
            }

            baseElement.view().makeSelection(this._elements);
        },
        rollback: function(){
            var baseElement = null;
            each(this._originalPositions, function(e){
                e.element.position(e.position);
                baseElement = e.element;
            });

            if (baseElement){
                baseElement.view().makeSelection(toArray(this._originalPositions, function(e){ return e.element }));
            }
        }
    });
})(sketch.framework.commands);